Kokaの例: State
state effectを定義
code:koka(ts)
effect state<a>
fun get() : a
fun set(x: a) : ()
2つのoperationを定義している
与えられた数値から0まで足し合わす関数を定義
code:koka(ts)
fun sumdown(sum: int = 0): <state<int>,div> int
val i = get()
if i <= 0 then sum else
set(i - 1)
sumdown(sum + i)
valは定数宣言
内部でget()/set()を使っているので、stateを持ち、
再帰しているのでdivも持つ
この時点では、どこかからgetして、どこかにsetする、と言ってるだけmrsekut.icon
実際にその保存先がどこなのかは、sumdownは言及しない
interfaceだけ書き、実装は書かれていない
state effect用のhandlerを定義
code:koka(ts)
fun state(init: a, action: () -> <state<a>,div|e> b): <div|e> b
var st := init
with handler
fun get() st
fun set(i) st := i
action()
varでmutableな変数を宣言
getはその変数の値を読むだけ、setはその変数を更新する
あえてもう少し明示的に書くと
code:koka(js)
fun state(init: a, action: () -> <state<a>,div|e> b): <div|e> b
var st := init
with handler
ctl get()
val f = fn() { st }
resume(f())
ctl set(i)
val f = fn() { st := i }
resume(f())
action()
つまり、getもsetもresumeしている
呼び出す
sumdown()という処理を、state handlerを使って呼び出す
code:koka(ts)
state(10) { sumdown() } // 55
他の例
以下のようにn番目のフィボナッチ数を求める関数を用意する
code:koka(ts)
fun fibonacci(n: int): <state<(int, int)>,div> int
val (a, b): (int, int) = get()
if n <= 1 then a else
set( (b, a + b) )
fibonacci(n - 1)
get()の返り値部分にtype annotation付けないとerrorになったmrsekut.icon
関数のeffect typeから推論してくれ〜、と思ったが難しいのか
valに対するannotationの付け方わからなかったけど勘で書いたらいけたmrsekut.icon
呼び出す
code:koka(ts)
state((0, 1)) { fibonacci(50) } // 7778742049
メモ化してる実装なので普通に速いmrsekut.icon
参考